<?php
namespace App\Services\User\Menu;

use App\Models\User\Menu;
use App\Models\User\RoleShowMenu;
use App\Services\User\ValidateMenu;
use App\Services\Manage\ManageIndex;
use App\Services\User\App;
use Illuminate\Support\Facades\DB;
/**
 * @Author: 蒋哲
 * @Date:   2017-05-27 16:25:06
 * @Last Modified by:   ws
 * @Last Modified time: 2018-06-12 
 */
class MenuLogic
{
    // 增加一个顶级菜单
    public function addTop(array $data): array
    {   
        $data['status'] = '1';
        $data['pid'] = '0';
        $data['level'] = '1';
        $data['update_time'] = $data['create_time'] = time();
        try{
            $res = Menu::insertGetId($data);
        }catch (\Exception $e) {
            // 当唯一键重复等报错时
            return server_err(null, '数据库异常:' . $e->getMessage());
        }
       // $res && $res = $this->model($this->menuModel)->getLastInsID();
        // 给超级系统管理员绑定展示权限
        $bindRes = $this->bindMenuShowAtuh($res);
        $resMsg = $res ? '成功增加一个顶级菜单' : '增加一个顶级菜单失败';
        $resMsg .= ',' . $bindRes['msg'];
        return auto_return($res, $resMsg, $resMsg);
    }
    // 增加一个非顶级菜单
    public function add(array $data): array
    {
        $data['status'] = '1';
        try{
            $res = Menu::insertGetId($data);
        }catch (\Exception $e) {
            // 当唯一键重复等报错时
            return server_err(null, '数据库异常:' . $e->getMessage());
        }
        //$res && $res = $this->model($this->menuModel)->getLastInsID();
        // 给超级系统管理员绑定展示权限
        $bindRes = $this->bindMenuShowAtuh($res);
        $resMsg = $res ? '成功增加一个非顶级菜单' : '增加一个非顶级菜单失败';
        $resMsg .= ',' . $bindRes['msg'];
        return auto_return($res, $resMsg, $resMsg);
    }
    // 为超级系统管理员绑定展示某菜单的权限
    private function bindMenuShowAtuh(int $menuId): array
    {
        if ($menuId) {
            $data['menu_id'] = $menuId;
            $data['role_id'] = SUPPER_ADMIN_ROLE_ID;
            $res = $this->addShowMenuAuthByRole($data);
        } else {
            $res['status'] = NULL_DATA_STATUS;
        }

        return auto_return($res['status'] === SUCCESS_STATUS, '为超级系统管理员绑定展示某菜单的权限成功', '为超级系统管理员绑定展示某菜单的权限失败');
    }
    // 获取某一菜单分类下的列表
    public function listByCate(array $data): array
    {
        $_where['menu_cate_id'] = $data['menu_cate_id'];
        $_where['status'] = 1;
        $query = Menu::where($_where);
        isset($data['menu_ids']) && $query->whereIn('id',$data['menu_ids']);
        $list = $query->orderBy('order')->get()->toArray();
        return auto_return($list, '成功获取某一菜单分类下的列表', '获取某一菜单分类下的列表失败');
    }
    // 获取某一菜单分类下的菜单树
    public function treeByCate(array $data): array
    {
        $listRes = $this->listByCate($data);

        if (SUCCESS_STATUS !== $listRes['status']) {
            return $listRes;
        }
        $tree = recursion($listRes['res'], false, 0, 1, 'pid', 'id', 'sub', 'level');
        return auto_return($tree, '成功获取某一菜单分类下的菜单树', '获取某一菜单分类下的菜单树失败');
    }
    // 停用某一菜单及其子菜单
   /* public function stop(array $data): array
    {
        $_where['id'] = $data['id'];
        $_where['status'] = '1';
        $res = $this->model($this->menuModel)->save(['status'=>'0'], $_where);
        return auto_return($res, '成功停用某一菜单及其子菜单', '停用某一菜单及其子菜单失败');
    }*/
    // 启用某一菜单及其子菜单
    /*public function start(array $data): array
    {
        $_where['id'] = $data['id'];
        $_where['status'] = '0';
        $res = $this->model($this->menuModel)->save(['status'=>'1'], $_where);
        return auto_return($res, '成功启用某一菜单及其子菜单', '启用某一菜单及其子菜单失败');
    }*/
    // 编辑某一菜单记录
    public function edit(array $data): array
    {
        $_where['id'] = $data['id'];
        $_where['status'] = '1';
        $save = make_map($data, ['name', 'name_cn', 'menu_cate_id', 'pid', 'order', 'level']);
        $res = Menu::where([['id','=',$data['id']],['status','=',1]])->update($save);
        return auto_return($res, '成功编辑某一菜单记录', '编辑某一菜单记录失败');
    }
    // 移动某一菜单记录及其子记录到另一记录下
    public function move(array $data): array
    {
        $_where['id'] = $data['id'];
        $res = Menu::where('id','=',$data['id'])->update(['pid'=>$data['pid']]);
        return auto_return($res, '成功移动某一菜单记录及其子记录到另一记录下', '移动某一菜单记录及其子记录到另一记录下失败');
    }
    // 根据app_key获取其对应的树形菜单
    public function treeByAppKey(array $data): array
    {
        $findRes = (new App())->find(['app_key'=>$data['app_key']]);
        if($findRes['status'] != SUCCESS_STATUS){
            return $findRes ;
        }
        $listByAppRes = (new MenuCateLogic())->listByApp(['app_id'=>$findRes['res']['id']]);
         if (\SUCCESS_STATUS !== $listByAppRes['status']) { return $listByAppRes; }
        // 获取某一菜单分类下的菜单树  serveruser/menu/Menu/treeByCate {"menu_cate_id":"1"}
        $trees = [];
        foreach($listByAppRes['res'] as $k => $v){
            $treeByCateRes = $this->treeByCate(['menu_cate_id'=>$v['id']]);  
            \SUCCESS_STATUS === $treeByCateRes['status'] && $trees[] = $treeByCateRes['res'];
        }
        return auto_return($trees, '成功获取后台菜单', '获取后台菜单失败');
    }
    // 为某一角色增加某一菜单的(展示权限) 仅是可展示,该菜单的功能能否被访问,取决于权限是否被允许
    public function addShowMenuAuthByRole(array $data): array
    {
        $save['menu_id'] = $data['menu_id'];
        $save['role_id'] = $data['role_id'];
        $save['status'] = '1';
        $save['create_time'] = time();
        $save['update_time'] = time();
        try{
            $res = RoleShowMenu::insertGetId($save);
        }catch (\Exception $e) {
            // 当唯一键重复等报错时
            return server_err(null, '数据库异常:' . $e->getMessage());
        }
        return auto_return($res, '成功增加一条记录', '增加一条记录失败');
    }

    // 为某一角色增加某一菜单及其可用子菜单的(展示权限)
    public function addShowMenuAndChildren(array $data): array
    {
        // 先查找该menu_id的子ID
        $idsRes = $this->getChildren($data['menu_id']);
        if (\SUCCESS_STATUS !== $idsRes['status']) {
            return $idsRes;
        }
        $save = [];
        foreach ($idsRes['res'] as $k => $v) {
            $temp['menu_id'] = $v;
            $temp['role_id'] = $data['role_id'];
            $temp['status'] = '1';
            $temp['create_time'] = time();
            $temp['update_time'] = time();
            $save[] = $temp;
        }

        // 将所有子ID形成相关数据,保存至数据库
        try{
            $res = RoleShowMenu::insert($save);
            $res = DB::getPdo()->lastInsertId();
        }catch (\Exception $e) {
            // 当唯一键重复等报错时
            return server_err(null, '数据库异常:' . $e->getMessage());
        }
        return auto_return($res, '成功增加记录', '增加记录失败'); 
    }
    // 根据一个菜单的ID,查找其子IDS及其本身ID
    private function getChildren(int $parentId): array
    {
    $find = Menu::where([['id','=',$parentId],['status','=',1]])->first(['menu_cate_id','type']);
        if (is_null($find)) {
            $res = [$parentId];
        } else {
            $list =  Menu::where([['menu_cate_id','=',$find['menu_cate_id']],['type','=',$find['type']]])->get(['id','pid','name'])->toArray();
            $ids = '';
            recursion($list, true, 0, 1, 'pid', 'id', 'sub', 'level', $ids);
            $res = explode(',', $ids);
        }
        return auto_return($res);
    }
    // 获取某角色集某app_key应用下的树形菜单
    /*public function treeByRolesAndAppkey(array $data): array
    {
        // 先查找用户角色可以显示的菜单
        $_where['status'] = '1';
        if (isset($data['role_ids']) && $data['role_ids']){
            $_where['role_id'] = ['in', $data['role_ids']];
        } else {
            // 根据角色去取id
            $roleIdsRes = $this->logic($this->roleLogic)->getIdsByRoles($data);
            if (SUCCESS_STATUS !== $roleIdsRes['status']) { return $roleIdsRes; }
            $_where['role_id'] = ['in', $roleIdsRes['res']['ids']];
        }
        $showMenuIds = $this->model($this->roleShowMenuModel)
                            ->where($_where)
                            ->column('menu_id');
        if (!$showMenuIds) { return null_data(null, '没有可显示的菜单树'); }
        $showMenuIds = array_unique($showMenuIds);
        // 再根据菜单ID 和 应用ID 找出菜单列表
        // 根据app_key查找应用ID serveruser/auth/App/find   {"app_key":"4942b00d6a75eebcce692224b0cb3110"}
        $findRes = $this->logic($this->appLogic)->find(['app_key'=>$data['app_key']]);
        if (\SUCCESS_STATUS !== $findRes['status']) { return $findRes; }

        // 根据应用ID获取某一应用所有的可用菜单分类列表(不分页) serveruser/menu/MenuCate/listByApp {"app_id":"11"}
        $listByAppRes = $this->logic($this->menuCateLogic)->listByApp(['app_id'=>$findRes['res']['id']]);
        if (\SUCCESS_STATUS !== $listByAppRes['status']) { return $listByAppRes; }

        // 获取某一菜单分类下的菜单树  serveruser/menu/Menu/treeByCate {"menu_cate_id":"1"}
        $trees = [];
        foreach($listByAppRes['res'] as $k => $v){
            $treeByCateRes = $this->treeByCate(['menu_cate_id'=>$v['id'], 'menu_ids'=>$showMenuIds]);  
            \SUCCESS_STATUS === $treeByCateRes['status'] && $trees[] = $treeByCateRes['res'];
        }

        return auto_return($trees, '成功获取某角色集某app_key应用下的树形菜单', '获取某角色集某app_key应用下的树形菜单失败');
    }*/
    // 停止某一角色某一菜单的(展示权限)
    public function stopShowMenuAuthByRole(array $data): array
    {
        $_where =[];
        if($data['id'] != ''){
             $_where[] =['id','=',$data['id']];
        }
        if($data['role_id'] != ''){
             $_where[] =['role_id','=',$data['role_id']];
        }
        if($data['menu_id'] != ''){
             $_where[] =['menu_id','=',$data['menu_id']];
        }
       
        $res = RoleShowMenu::where($_where)->update(['status' => 0,'update_time' => time()]);
        return auto_return($res, '成功停止某一角色某一菜单的(展示权限)', '停止某一角色某一菜单的(展示权限)失败');
    }
    // 启用某一角色某一菜单的(展示权限)
    public function startShowMenuAuthByRole(array $data): array
    {
        $_where =[];
        if($data['id'] != ''){
             $_where[] =['id','=',$data['id']];
        }
        if($data['role_id'] != ''){
             $_where[] =['role_id','=',$data['role_id']];
        }
        if($data['menu_id'] != ''){
             $_where[] =['menu_id','=',$data['menu_id']];
        }
        $res = RoleShowMenu::where($_where)->update(['status' => 1,'update_time' => time()]);
        return auto_return($res, '成功启用某一角色某一菜单的(展示权限)', '启用某一角色某一菜单的(展示权限)失败');
    }
    // 启用或停止某一角色某一菜单及其可用子菜单的(展示权限)
    private function startOrStopShowMenuAndChildren(array $data, int $status, string $msg): array
    {
         // 如果传的是id,先根据此找出menu_id
        if ($data['id'] !== '' && $data['menu_id'] === '') {
            $_where['id'] = $data['id'];
            $find = RoleShowMenu::where($_where)->first();
            if (!$find) {
                return null_data(null, '根据此ID没有找到相关信息');
            }
            $data['role_id'] = $find['role_id'];
            $data['menu_id'] = $find['menu_id'];
        }
        // 先查找该menu_id的子ID
        $idsRes = $this->getChildren($data['menu_id']);
        if (\SUCCESS_STATUS !== $idsRes['status']) {
            return $idsRes;
        }
        $res = RoleShowMenu::where('role_id','=',$data['role_id'])->whereIn('menu_id',$idsRes['res'])->update(['status'=>$status]);
        return auto_return($res, '成功' . $msg, $msg .'失败');
    }
    // 停止某一角色某一菜单及其可用子菜单的(展示权限)
    public function stopShowMenuAndChildren(array $data): array
    {
        $msg = '停止某一角色某一菜单及其可用子菜单的(展示权限)';
        return $this->startOrStopShowMenuAndChildren($data, 0, $msg);
    }
    // 启用某一角色某一菜单及其可用子菜单的(展示权限)
    public function startShowMenuAndChildren(array $data): array
    {
        $msg = '启用某一角色某一菜单及其可用子菜单的(展示权限)';
        return $this->startOrStopShowMenuAndChildren($data, 1, $msg);
    }

   
}